#include<stdlib.h>
#include<stdio.h>
#include<math.h>
#include<assert.h>
#include"Matrice.h"


int modulo(int x, int y)
{
	int t;
	t=x/y;
	t=x-y*t;
	if(t<0)
	{
		return y+t;
	}
	else
	{
		return t;
	}
}

void afficheVecteur(vecteur v)
{
	printf("x : %d, y : %d, z : %d\n",v.x,v.y,v.z);
}

void directionVecteur(char direction, vecteur * v)
{
	
/* verification des precondition*/
	assert(direction=='h' || direction=='b' || direction=='d' || direction=='g' || direction=='a' || direction=='p');
	

	
	switch(direction)
	{
		case 'd' :
			v->x=1;
			v->y=0;
			v->z=0;
			break;
		case 'g' :
			v->x=-1;
			v->y=0;
			v->z=0;
			break;
		case 'a' :
			v->x=0;
			v->y=1;
			v->z=0;
			break;
		case 'p' :
			v->x=0;
			v->y=-1;
			v->z=0;
			break;
		case 'h' :
			v->x=0;
			v->y=0;
			v->z=1;
			break;
		case 'b' :
			v->x=0;
			v->y=0;
			v->z=-1;
			break;
	}
	
}

void changeSensVecteur(vecteur * v)
{
	vecteur t,r;
	
	t.x=0;
	t.y=0;
	t.z=0;
	
	soustraction(v,&t,&r,0);
	
	remplaceVecteur(v,&r);
}

void addition(vecteur *  v1, vecteur * v2, vecteur * v3, int n)
{	
	if(n==0)
	{
		v3->x=(v1->x+v2->x);
		v3->y=(v1->y+v2->y);
		v3->z=(v1->z+v2->z);
	}
	else{
	v3->x=modulo((v1->x+v2->x),n);
	v3->y=modulo((v1->y+v2->y),n);
	v3->z=modulo((v1->z+v2->z),n);}
}


void soustraction(vecteur * v1, vecteur * v2, vecteur * v3, int n)
{
	if(n==0)
	{
		v3->x=(v1->x-v2->x);
		v3->y=(v1->y-v2->y);
		v3->z=(v1->z-v2->z);
	}
	else{
	v3->x=modulo((v1->x-v2->x),n);
	v3->y=modulo((v1->y-v2->y),n);
	v3->z=modulo((v1->z-v2->z),n);}
}

void produit(vecteur * v1, int k, vecteur * v2, int n)
{
	if(n==0)
	{
		v2->x=(k*v1->x);
	v2->y=(k*v1->y);
	v2->z=(k*v1->z);
	}
	else{
	v2->x=modulo((k*v1->x),n);
	v2->y=modulo((k*v1->y),n);
	v2->z=modulo((k*v1->z),n);}
}

int compareVecteur(vecteur * v1, vecteur * v2)
{
	if(v1->x==v2->x && v2->y==v1->y && v1->z==v2->z)
	{
		return 1;
	}
	else{ return 0;}
}


char sensDirection(vecteur * v2,vecteur * v1,int n)
{
	vecteur temp,add;
	
/* Pour obtenir la direction du vecteur (v2-v1), on regarde quelle direction il faut ajouter a v1 pour obtenir v2 */
	directionVecteur('d',&temp);
	addition(v1,&temp,&add,n);
	if(compareVecteur(&add,v2)){return 'd';}
	
	directionVecteur('g',&temp);
	addition(v1,&temp,&add,n);
	if(compareVecteur(&add,v2)){return 'g';}
	
	directionVecteur('a',&temp);
	addition(v1,&temp,&add,n);
	if(compareVecteur(&add,v2)){return 'a';}
	
	directionVecteur('p',&temp);
	addition(v1,&temp,&add,n);
	if(compareVecteur(&add,v2)){return 'p';}
	
	directionVecteur('h',&temp);
	addition(v1,&temp,&add,n);
	if(compareVecteur(&add,v2)){return 'h';}
	
	directionVecteur('b',&temp);
	addition(v1,&temp,&add,n);
	if(compareVecteur(&add,v2)){return 'b';}
	else{return 0;}
}

void remplaceVecteur(vecteur * v1, vecteur * v2)
{
	v1->x=v2->x;
	v1->y=v2->y;
	v1->z=v2->z;
}



void initMatrice(matrice * m)
{
	m->c1=(vecteur*)malloc(sizeof(vecteur));
	m->c2=(vecteur*)malloc(sizeof(vecteur));
	m->c3=(vecteur*)malloc(sizeof(vecteur));
	
	m->c1->x=1;
	m->c2->y=1;
	m->c3->z=1;
	
	m->c1->y=0;
	m->c2->z=0;
	m->c3->x=0;
	m->c1->z=0;
	m->c2->x=0;
	m->c3->y=0;
}

void freeMatrice(matrice * m)
{
	free(m->c1);
	free(m->c2);
	free(m->c3);
}

void translationMatrice(vecteur * v, matrice * m)
{
	matrice temp,id;
	initMatrice(&temp);
	
	initMatrice(&id);
	
	remplaceVecteur(temp.c1,v);
	remplaceVecteur(temp.c2,v);
	remplaceVecteur(temp.c3,v);
	
	sommeMatriceCarre(&id,&temp,m);
	
	freeMatrice(&temp);
	freeMatrice(&id);
}

void sommeMatriceCarre(matrice * m1,matrice * m2, matrice * m3)
{
	m3->c1->x=m1->c1->x+m2->c1->x;
	m3->c1->y=m1->c1->y+m2->c1->y;
	m3->c1->z=m1->c1->z+m2->c1->z;
	m3->c2->x=m1->c2->x+m2->c2->x;
	m3->c2->y=m1->c2->y+m2->c2->y;
	m3->c2->z=m1->c2->z+m2->c2->z;
	m3->c3->x=m1->c3->x+m2->c3->x;
	m3->c3->y=m1->c3->y+m2->c3->y;
	m3->c3->z=m1->c3->z+m2->c3->z;
	
}



void differenceMatriceCarre(matrice * m1,matrice * m2, matrice * m3)
{
	m3->c1->x=m1->c1->x-m2->c1->x;
	m3->c1->y=m1->c1->y-m2->c1->y;
	m3->c1->z=m1->c1->z-m2->c1->z;
	m3->c2->x=m1->c2->x-m2->c2->x;
	m3->c2->y=m1->c2->y-m2->c2->y;
	m3->c2->z=m1->c2->z-m2->c2->z;
	m3->c3->x=m1->c3->x-m2->c3->x;
	m3->c3->y=m1->c3->y-m2->c3->y;
	m3->c3->z=m1->c3->z-m2->c3->z;
	
}

void produitMatriceCarre(matrice * m1,matrice * m2, matrice * m3)
{
  (m3->c1)->x=((m2->c1)->x)*((m1->c1)->x)+((m2->c2)->x)*((m1->c1)->y)+((m2->c3)->x)*((m1->c1)->z);
  (m3->c1)->y=((m2->c1)->y)*((m1->c1)->x)+((m2->c2)->y)*((m1->c1)->y)+((m2->c3)->z)*((m1->c1)->z);
  (m3->c1)->z=((m2->c1)->z)*((m1->c1)->x)+((m2->c2)->z)*((m1->c1)->y)+((m2->c3)->z)*((m1->c1)->z);

  (m3->c2)->x=((m2->c1)->x)*((m1->c2)->x)+((m2->c2)->x)*((m1->c2)->y)+((m2->c3)->x)*((m1->c2)->z);
  (m3->c2)->y=((m2->c1)->y)*((m1->c2)->x)+((m2->c2)->y)*((m1->c2)->y)+((m2->c3)->y)*((m1->c2)->z);
  (m3->c2)->z=((m2->c1)->z)*((m1->c2)->x)+((m2->c2)->z)*((m1->c2)->y)+((m2->c3)->z)*((m1->c2)->z);

  (m3->c3)->x=((m2->c1)->x)*((m1->c3)->x)+((m2->c2)->x)*((m1->c3)->y)+((m2->c3)->x)*((m1->c3)->z);
  (m3->c2)->y=((m2->c1)->y)*((m1->c2)->x)+((m2->c2)->y)*((m1->c2)->y)+((m2->c3)->y)*((m1->c2)->z);
  (m3->c2)->z=((m2->c1)->z)*((m1->c2)->x)+((m2->c2)->z)*((m1->c2)->y)+((m2->c3)->z)*((m1->c2)->z);
}


void fonctionMatrice(matrice * m1, vecteur * v1, vecteur * v2,int n)
{ 
  v2->x=modulo((((m1->c1)->x)*(v1->x)+((m1->c2)->x)*(v1->y)+((m1->c3)->x)*(v1->z)),n);
  v2->y=modulo((((m1->c1)->y)*(v1->x)+((m1->c2)->y)*(v1->y)+((m1->c3)->y)*(v1->z)),n);
  v1->z=modulo((((m1->c1)->z)*(v1->x)+((m1->c2)->z)*(v1->y)+((m1->c3)->z)*(v1->z)),n);
}

